package com.eq.util;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import io.jsonwebtoken.Jwts;

public class ConfigurationManager {
    private static final Map<String, String> REQUIRED_PROPERTIES = new HashMap<>();
    static {
        REQUIRED_PROPERTIES.put("server.port", "The port on which the server will run.");
        REQUIRED_PROPERTIES.put("jwt.secret", "The secret key used for JWT token generation.");
        REQUIRED_PROPERTIES.put("jwt.expiration",
                "The expiration time (in seconds) for JWT tokens. Usually 86400 (24 hours).");
        REQUIRED_PROPERTIES.put("app.user.username", "The default username for the application.");
        REQUIRED_PROPERTIES.put("app.user.password", "The default password for the application.");
        REQUIRED_PROPERTIES.put("file.upload-dir", "The directory where uploaded files will be stored.");
    }

    public static void generatePropertiesFile() {
        // Prompt user for input
        System.out.println("Please enter the path of 'application.properties':");
        Scanner scanner = new Scanner(System.in);
        String propertiesPath = scanner.nextLine();

        Properties properties = loadProperties(propertiesPath);
        boolean updated = false;

        for (String key : REQUIRED_PROPERTIES.keySet()) {
            String value = properties.getProperty(key);
            if (value == null || value.trim().isEmpty()) {
                value = getConfigurationValue(key, REQUIRED_PROPERTIES.get(key), scanner);
                properties.setProperty(key, value);
                updated = true;
            }
        }

        if (updated) {
            saveProperties(properties, propertiesPath);
        }
    }

    private static String getConfigurationValue(String key, String descriptor, Scanner scanner) {
        // If it is a JWT secret, generate one randomly
        if (key.equals("jwt.secret")) {
            return Base64.getEncoder().encodeToString(Jwts.SIG.HS256.key().build().getEncoded());
        }

        // Prompt user for input
        System.out.printf("'%s': %s\nPlease enter value: ", key, descriptor);
        String value = scanner.nextLine();

        // app.user.password must be encoded using BCryptPasswordEncoder
        if (key.equals("app.user.password")) {
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            value = encoder.encode(value);
        }
        return value;
    }

    private static Properties loadProperties(String propertiesPath) {
        Properties properties = new Properties();
        try (FileInputStream input = new FileInputStream(propertiesPath)) {
            properties.load(input);
        } catch (IOException e) {
            // If file doesn't exist, create new properties
        }
        return properties;
    }

    private static void saveProperties(Properties properties, String propertiesPath) {
        try (FileOutputStream output = new FileOutputStream(propertiesPath)) {
            properties.store(output, "Updated configurations");
        } catch (IOException e) {
            System.err.println("Failed to save application.properties: " + e.getMessage());
        }
    }
}
